package com.xdxc.service.impl;


import com.alibaba.nacos.shaded.com.google.common.util.concurrent.RateLimiter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xdxc.exception.CustomException;
import com.xdxc.feign.GradingFeign;
import com.xdxc.mapper.ExamScoringTaskMapper;
import com.xdxc.mapper.ExamsMapper;
import com.xdxc.model.entity.ExamScoringTask;
import com.xdxc.model.entity.Exams;
import com.xdxc.model.entity.UserAnswer;
import com.xdxc.model.enums.ExamStatus;
import com.xdxc.model.form.GradingForm;
import com.xdxc.model.query.ExamsQuery;
import com.xdxc.response.Result;
import com.xdxc.service.ExamsService;
import com.xdxc.service.UserAnswerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class GradingService {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private UserAnswerService userAnswerService;

    @Autowired
    private GradingFeign gradingFeign;
    @Autowired
    private ExamsService examsService;

    @Autowired
    private ExamsMapper examsMapper;


    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ExamScoringTaskMapper taskMapper;


    public Result sendUserAnswers(Long examId){
        //查询是否结束

       Exams exams= examsService.getById(examId);
        if(exams==null){
            throw new CustomException(400,"考试不存在");
        }
        ExamsQuery examsQuery=ExamsQuery.builder()
                .examId(exams.getId())
                .examName(exams.getTitle())
                .build();
        Result<GradingForm>  result=gradingFeign.getExamProgress(examsQuery);
        if (result.getCode()!=1){
            throw new CustomException(result.getCode(),result.getMsg());
        }
        GradingForm gradingForm=result.getData();
        ExamStatus status = ExamStatus.fromCode(gradingForm.getIsEnd());
        status.handle(); // 自动调用对应的逻辑
        userAnswerService.sendExamAnswers(examId);
        return Result.success("批改程序启动");

    }

//    @Scheduled(fixedRate = 30 * 60 * 1000, initialDelay = 5000)
//    public void scanFinishedExams() {
//        // 获取分布式锁，防止多个实例同时执行
//        RLock lock = redissonClient.getLock("lock:scan:finished:exams");
//        try {
//            if (lock.tryLock(10, 60, TimeUnit.SECONDS)) {
//                log.info("开始扫描已结束考试...");
//
//                // 1. 查询已结束但未生成评分任务的考试
//                List<Exams> finishedExams = examsMapper.selectFinishedExamsWithoutTask();
//
//                // 2. 为每个考试创建评分任务
//                finishedExams.forEach(exam -> {
//                    try {
//                        // 2.1 创建评分任务记录
//                        ExamScoringTask task = new ExamScoringTask();
//                        task.setExamId(exam.getId());
//                        task.setExamName(exam.getTitle());
//                        task.setStatus(0); // 待处理
//                        taskMapper.insert(task);
//                        // 2.2 发送到评分队列
//                        sendToScoringQueue(exam.getId(), exam.getTitle());
//
//                        log.info("已创建评分任务，考试ID: {}, 任务ID: {}", exam.getId(), task.getId());
//                    } catch (Exception e) {
//                        log.error("创建评分任务失败，考试ID: {}", exam.getId(), e);
//                    }
//                });
//
//                // 3. 检查超时任务并重试
//                retryTimeoutTasks();
//            }
//        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
//            log.error("获取分布式锁被中断", e);
//        } finally {
//            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
//                lock.unlock();
//            }
//        }
//    }

    private void sendToScoringQueue(Long examId, String examName) {
        try {
            // 构造消息内容
            Map<String, Object> messageContent = new HashMap<>();
            messageContent.put("examId", examId);
            messageContent.put("examName", examName);
            messageContent.put("timestamp", System.currentTimeMillis());

            // 创建 RocketMQ 消息
            Message<Map<String, Object>> message = MessageBuilder.withPayload(messageContent)
                    .setHeader(RocketMQHeaders.KEYS, examId)
                    .setHeader(RocketMQHeaders.TAGS, "scoring_task")
                    .build();

            // 发送消息，设置延迟级别（如果需要延迟重试）
            // RocketMQ 延迟级别：1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
            // 对应 level 1-18，这里设置30分钟对应 level=16
            rocketMQTemplate.syncSend("exam_scoring_topic", message, 30000, 16);

            log.info("成功发送评分任务到RocketMQ，考试ID: {}, 任务ID: {}", examId, examName);
        } catch (Exception e) {
            log.error("发送评分任务到RocketMQ失败，考试ID: {}, 任务ID: {}", examId, examName, e);
            // 可以添加重试逻辑或告警
        }
    }

    private void retryTimeoutTasks() {
        // 查询处理中超时(超过30分钟)的任务
        List<ExamScoringTask> timeoutTasks = taskMapper.selectTimeoutTasks(
                LocalDateTime.now().minusMinutes(30),
                3 // 最大重试次数
        );

        timeoutTasks.forEach(task -> {
            try {
                // 更新任务状态为待处理
                task.setStatus(0);
                task.setRetryCount(task.getRetryCount() + 1);
                task.setNextRetryTime(LocalDateTime.now().plusMinutes(30));
                taskMapper.updateById(task);

                // 重新发送到RocketMQ队列
                sendToScoringQueue(task.getExamId(), task.getExamName());

                log.warn("重试超时评分任务，考试ID: {}, 任务ID: {}, 重试次数: {}",
                        task.getExamId(), task.getId(), task.getRetryCount());
            } catch (Exception e) {
                log.error("重试评分任务失败，考试ID: {}, 任务ID: {}",
                        task.getExamId(), task.getId(), e);
            }
        });
    }

}
